/*
 * SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#![allow(clippy::too_many_arguments)]

use crate::common::*;
use crate::utpam::*;
use crate::utpam_strerror::utpam_strerror;
use crate::utpam_syslog::*;
use crate::{pam_syslog, D};

use crate::utpam_dynamic::{utpam_dlopen, utpam_dlsym};
use crate::utpam_misc::{
    utpam_mkargv, utpam_parse_control, utpam_set_default_control, utpam_tokenize,
};
use std::env::consts::ARCH;
use std::path::Path;
use utpam_internal::utpam_line::{utpam_line_assemble, UtpamLineBuffer};

use std::cell::RefCell;
use std::fs::{metadata, File, OpenOptions};
use std::io::BufReader;
use std::path::PathBuf;
use std::rc::Rc;

#[cfg(feature = "PAM_LOCKING")]
use crate::utpam_delay::{utpam_await_timer, utpam_fail_delay};

const PAM_T_ANY: i32 = 0;
const PAM_T_AUTH: i32 = 1;
const PAM_T_SESS: i32 = 2;
const PAM_T_ACCT: i32 = 4;
const PAM_T_PASS: i32 = 8;

const UNKNOWN_MODULE: &str = "unknown module";
const DEFAULT_MODULE_PATH: &str = "/lib64/utpam";

//初始化UtpamHandle结构体字段
pub fn utpam_init_handlers(utpamh: &mut Box<UtpamHandle>) -> u8 {
    let mut retval: u8;

    D!("called.");

    //如果所有内容都已加载，则立即返回
    if utpamh.handlers.handlers_loaded != 0 {
        return PAM_SUCCESS;
    }

    D!("initializing");

    if utpamh.service_name.is_empty() {
        return PAM_BAD_ITEM;
    }

    /* Is the PAM subsystem locked？*/
    #[cfg(feature = "PAM_LOCKING")]
    {
        match File::open(UTPAM_LOCK_FILE) {
            Ok(_) => {
                pam_syslog!(
                    &utpamh,
                    LOG_ERR,
                    "utpam_init_handlers: UTPAM lockfile (UTPAM_LOCK_FILE) exists - aborting",
                );
                utpamh.fail_delay.utpam_start_timer();
                utpam_fail_delay(utpamh, 5000000);
                utpam_await_timer(utpamh, PAM_ABORT);
                return PAM_ABORT;
            }
            Err(e) => {
                pam_syslog!(
                    &utpamh,
                    LOG_ERR,
                    "utpam_init_handlers: Failed to open UTPAM_LOCK_FILE file - {}",
                    e
                );
            }
        }
    }

    /*
     * Now parse the config file(s) and add handlers
     */
    {
        let mut path: Option<PathBuf> = None;
        let mut file: Option<File> = None;

        //检查配置目录是否存在
        let mut dir_exist: bool = false;
        if utpamh.confdir.exists()
            || check_directory(UTPAM_CONFIG_D)
            || check_directory(UTPAM_CONFIG_DIST_D)
        {
            dir_exist = true;
        }
        #[cfg(feature = "PAM_CONFIG_DIST2_D")]
        if check_directory(UTPAM_CONFIG_DIST2_D) {
            dir_exist = true;
        }

        if dir_exist {
            let mut read_something = 0;
            //打开配置文件并解析
            if utpam_open_config_file(utpamh, utpamh.service_name.clone(), &mut path, &mut file)
                == PAM_SUCCESS
            {
                //解析配置文件
                retval = utpam_parse_config_file(
                    utpamh,
                    file.as_mut().unwrap(),
                    Some(utpamh.service_name.clone()),
                    PAM_T_ANY,
                    0,
                    0,
                    #[cfg(feature = "PAM_READ_BOTH_CONFS")]
                    false,
                );
                if retval != PAM_SUCCESS {
                    let path = if let Some(s) = &path {
                        s.to_str().unwrap()
                    } else {
                        "unknown file"
                    };
                    pam_syslog!(
                        &utpamh,
                        LOG_ERR,
                        "utpam_init_handlers: error reading {}",
                        path
                    );
                    let err = utpam_strerror(LOG_ERR);
                    pam_syslog!(&utpamh, LOG_ERR, "utpam_init_handlers [{}]", err);
                } else {
                    read_something = 1;
                }
            } else {
                D!(
                    "unable to open configuration for: {:?}",
                    utpamh.service_name
                );
                #[cfg(feature = "PAM_READ_BOTH_CONFS")]
                D!("checking : {:?}", UTPAM_CONFIG);

                #[cfg(feature = "PAM_READ_BOTH_CONFS")]
                if !utpamh.confdir.exists() {
                    if let Ok(mut f) = File::open(UTPAM_CONFIG) {
                        retval = utpam_parse_config_file(
                            utpamh,
                            &mut f,
                            None,
                            PAM_T_ANY,
                            0,
                            0,
                            #[cfg(feature = "PAM_READ_BOTH_CONFS")]
                            true,
                        );
                    } else {
                        retval = PAM_SUCCESS;
                    }
                } else {
                    retval = PAM_SUCCESS;
                }
                #[cfg(not(feature = "PAM_READ_BOTH_CONFS"))]
                {
                    retval = PAM_SUCCESS;
                }
            }

            if retval == PAM_SUCCESS {
                if utpam_open_config_file(
                    utpamh,
                    UTPAM_DEFAULT_SERVICE.to_string(),
                    &mut path,
                    &mut file,
                ) == PAM_SUCCESS
                {
                    retval = utpam_parse_config_file(
                        utpamh,
                        file.as_mut().unwrap(),
                        Some(UTPAM_DEFAULT_SERVICE.to_string()),
                        PAM_T_ANY,
                        0,
                        0,
                        #[cfg(feature = "PAM_READ_BOTH_CONFS")]
                        false,
                    );
                    if retval != PAM_SUCCESS {
                        let path = if let Some(s) = &path {
                            s.to_str().unwrap()
                        } else {
                            "unknown file"
                        };
                        pam_syslog!(
                            &utpamh,
                            LOG_ERR,
                            "utpam_init_handlers: error reading {}",
                            path
                        );
                        let err = utpam_strerror(LOG_ERR);
                        pam_syslog!(&utpamh, LOG_ERR, "utpam_init_handlers: [{}]", err);
                    } else {
                        read_something = 1;
                    }
                } else {
                    D!(
                        "unable to open configuration for : {}",
                        UTPAM_DEFAULT_SERVICE
                    );
                    pam_syslog!(
                        &utpamh,
                        LOG_ERR,
                        "utpam_init_handlers: no default config {}",
                        UTPAM_DEFAULT_SERVICE
                    );
                }
                if read_something == 0 {
                    retval = PAM_ABORT;
                }
            }
        } else {
            let path = Path::new(UTPAM_CONFIG);
            match File::open(path) {
                Ok(ref mut file) => {
                    retval = utpam_parse_config_file(
                        utpamh,
                        file,
                        None,
                        PAM_T_ANY,
                        0,
                        0,
                        #[cfg(feature = "PAM_READ_BOTH_CONFS")]
                        false,
                    );
                }
                Err(_) => {
                    pam_syslog!(
                        &utpamh,
                        LOG_ERR,
                        "utpam_init_handlers: error reading {}",
                        UTPAM_CONFIG
                    );
                    return PAM_ABORT;
                }
            };
        }
    }

    if retval != PAM_SUCCESS {
        pam_syslog!(&utpamh, LOG_ERR, "error reading PAM configuration file",);
        return PAM_ABORT;
    }

    utpamh.handlers.handlers_loaded = 1;

    D!("exiting");
    PAM_SUCCESS
}

///检查指定路径是否存在且是目录
fn check_directory(pamh_confdir: &str) -> bool {
    metadata(pamh_confdir).is_ok_and(|md| md.file_type().is_dir())
}

///打开配置文件
fn utpam_open_config_file(
    utpamh: &mut Box<UtpamHandle>,
    service: String,
    path: &mut Option<PathBuf>,
    file: &mut Option<File>,
) -> u8 {
    let mut path_buf = PathBuf::new();

    let dirs = [UTPAM_CONFIG_D, UTPAM_CONFIG_DIST_D];

    //处理提供了绝对路径和配置目录的情况
    if service.starts_with('/') {
        path_buf = PathBuf::from(service.clone());
    } else if utpamh.confdir.exists() {
        path_buf = utpamh.confdir.join(service.clone());
    }
    if path_buf.is_file() {
        D!("opening {:?}", path_buf);

        let fd = OpenOptions::new().read(true).open(&path_buf);
        match fd {
            Ok(f) => {
                *path = Some(path_buf);
                *file = Some(f);
                return PAM_SUCCESS;
            }
            Err(err) => {
                pam_syslog!(&utpamh, LOG_ERR, "{}", err);
                return PAM_ABORT;
            }
        }
    }

    //打开默认配置目录下的文件
    for dir in dirs {
        let dir = PathBuf::from(dir);
        path_buf = dir.join(service.clone());
        if path_buf.exists() {
            D!("opening {:?}", path_buf);

            let fd = OpenOptions::new().read(true).open(&path_buf);
            match fd {
                Ok(f) => {
                    *path = Some(path_buf);
                    *file = Some(f);
                    return PAM_SUCCESS;
                }
                Err(err) => {
                    pam_syslog!(&utpamh, LOG_ERR, "{}", err);
                    return PAM_ABORT;
                }
            }
        } else {
            D!("File or directory not found: {:?}", path_buf);
        }
    }

    PAM_ABORT
}

//加载并解析指定的配置文件
fn utpam_load_conf_file(
    utpamh: &mut Box<UtpamHandle>,
    config_name: Option<String>,
    service: Option<String>,
    module_type: i32,
    include_level: i32,
    stack_level: i32,
    #[cfg(feature = "PAM_READ_BOTH_CONFS")] not_other: bool,
) -> u8 {
    let mut file: Option<File> = None;
    let mut path: Option<PathBuf> = None;
    let mut retval: u8 = PAM_ABORT;

    D!("called.");

    //检查是否超过了最大允许的嵌套层次
    if include_level >= PAM_SUBSTACK_MAX_LEVEL {
        D!("maximum level of inclusions reached");
        pam_syslog!(&utpamh, LOG_ERR, "maximum level of inclusions reached",);
        return PAM_ABORT;
    }

    //检查配置文件名
    let config_name = match config_name {
        Some(name) => name,
        None => {
            D!("no config file supplied");
            pam_syslog!(&utpamh, LOG_ERR, "({:?}) no config name supplied", service);
            return PAM_ABORT;
        }
    };

    //打开配置文件
    if utpam_open_config_file(utpamh, config_name.clone(), &mut path, &mut file) == PAM_SUCCESS {
        //解析配置文件
        retval = utpam_parse_config_file(
            utpamh,
            file.as_mut().expect("File is not available."),
            service,
            module_type,
            include_level,
            stack_level,
            #[cfg(feature = "PAM_READ_BOTH_CONFS")]
            not_other,
        );
        if retval != PAM_SUCCESS {
            let err = utpam_strerror(retval);
            pam_syslog!(
                &utpamh,
                LOG_ERR,
                "utpam_load_conf_file: error reading {:?}: {}",
                path,
                err
            );
        }
    } else {
        D!(
            "utpam_load_conf_file: unable to open config for {}",
            config_name
        );
        pam_syslog!(
            &utpamh,
            LOG_ERR,
            "utpam_load_conf_file: unable to open config for {}",
            config_name
        );
    }
    retval
}

//解析配置文件
fn utpam_parse_config_file(
    utpamh: &mut Box<UtpamHandle>,
    file: &mut File,
    known_service: Option<String>,
    requested_module_type: i32,
    include_level: i32,
    stack_level: i32,
    #[cfg(feature = "PAM_READ_BOTH_CONFS")] not_other: bool,
) -> u8 {
    let mut f = BufReader::new(file);
    let mut buffer = UtpamLineBuffer::default();
    let repl = String::from(" ");

    //逐行处理配置文件内容
    let mut x = utpam_line_assemble(&mut f, &mut buffer, repl.clone());
    while x > 0 {
        let mut mod_path;
        let mut buf = Some(buffer.assembled.as_str());
        let mut res;
        let mut argc = 0;
        let mut argv: Vec<String> = vec![];
        let other: bool;
        let mut handler_type = PAM_HT_MODULE;
        let module_type;
        let mut actions: Vec<i32> = vec![0; PAM_RETURN_VALUES];
        let tok;

        D!("LINE: {:?}", buf);
        //判断是否提供服务名称
        let this_service = match known_service {
            Some(ref s) => {
                //nexttok = Some(s.clone());
                s.clone()
            }
            None => match utpam_tokenize(None, &mut buf) {
                Some(s) => {
                    tok = s;
                    tok.clone()
                }
                None => String::from(""),
            },
        };

        #[cfg(feature = "PAM_READ_BOTH_CONFS")]
        {
            other = if not_other {
                false
            } else {
                this_service.eq_ignore_ascii_case(UTPAM_DEFAULT_SERVICE)
            };
        }

        #[cfg(not(feature = "PAM_READ_BOTH_CONFS"))]
        {
            other = this_service.eq_ignore_ascii_case(UTPAM_DEFAULT_SERVICE);
        }

        let accspt = this_service.eq_ignore_ascii_case(&utpamh.service_name.clone());

        if accspt || other {
            let mut pam_include = 0;
            let mut substack = 0;

            D!("Found PAM config entry for: {}", this_service);

            match utpam_tokenize(None, &mut buf) {
                Some(mut tok) => {
                    if tok.starts_with('-') {
                        handler_type = PAM_HT_SILENT_MODULE;
                        tok = tok.strip_prefix('-').unwrap().to_string();
                    }
                    if tok.eq_ignore_ascii_case("auth") {
                        module_type = PAM_T_AUTH;
                    } else if tok.eq_ignore_ascii_case("session") {
                        module_type = PAM_T_SESS;
                    } else if tok.eq_ignore_ascii_case("account") {
                        module_type = PAM_T_ACCT;
                    } else if tok.eq_ignore_ascii_case("password") {
                        module_type = PAM_T_PASS;
                    } else {
                        D!("bad module type: {}", tok);
                        pam_syslog!(
                            &utpamh,
                            LOG_ERR,
                            "({}) illegal module type: {}",
                            this_service,
                            tok
                        );
                        module_type = if requested_module_type != PAM_T_ANY {
                            requested_module_type
                        } else {
                            PAM_T_AUTH
                        };

                        handler_type = PAM_HT_MUST_FAIL;
                    }
                }
                None => {
                    D!("empty module type for {}", this_service);
                    pam_syslog!(&utpamh, LOG_ERR, "({}) empty module type", this_service);
                    module_type = if requested_module_type != PAM_T_ANY {
                        requested_module_type
                    } else {
                        PAM_T_AUTH
                    };

                    handler_type = PAM_HT_MUST_FAIL;
                }
            };

            D!(
                "Using config entry: {:?}, handler_type: {}",
                buf,
                handler_type
            );

            if requested_module_type != PAM_T_ANY && module_type != requested_module_type {
                D!(
                    "Skipping config entry: {:?} (requested={}, found={})",
                    buf,
                    requested_module_type,
                    module_type
                );
                x = utpam_line_assemble(&mut f, &mut buffer, repl.clone());
                continue;
            }

            for item in actions.iter_mut().take(PAM_RETURN_VALUES) {
                *item = PAM_ACTION_UNDEF;
            }

            //读取控制标志
            match utpam_tokenize(None, &mut buf) {
                Some(tok) => {
                    //将tok转换为小写字母后进行匹配
                    match tok.to_ascii_lowercase().as_str() {
                        "required" => {
                            D!("*PAM_F_REQUIRED*");
                            actions[PAM_SUCCESS as usize] = PAM_ACTION_OK;
                            actions[PAM_NEW_AUTHTOK_REQD as usize] = PAM_ACTION_OK;
                            actions[PAM_IGNORE as usize] = PAM_ACTION_IGNORE;
                            utpam_set_default_control(&mut actions, PAM_ACTION_BAD);
                        }
                        "requisite" => {
                            D!("*PAM_F_REQUISITE*");
                            actions[PAM_SUCCESS as usize] = PAM_ACTION_OK;
                            actions[PAM_NEW_AUTHTOK_REQD as usize] = PAM_ACTION_OK;
                            actions[PAM_IGNORE as usize] = PAM_ACTION_IGNORE;
                            utpam_set_default_control(&mut actions, PAM_ACTION_DIE);
                        }
                        "optional" => {
                            D!("*PAM_F_OPTIONAL*");
                            actions[PAM_SUCCESS as usize] = PAM_ACTION_OK;
                            actions[PAM_NEW_AUTHTOK_REQD as usize] = PAM_ACTION_OK;
                            actions[PAM_IGNORE as usize] = PAM_ACTION_IGNORE;
                            utpam_set_default_control(&mut actions, PAM_ACTION_IGNORE);
                        }
                        "sufficient" => {
                            D!("*PAM_F_SUFFICIENT*");
                            actions[PAM_SUCCESS as usize] = PAM_ACTION_DONE;
                            actions[PAM_NEW_AUTHTOK_REQD as usize] = PAM_ACTION_DONE;
                            actions[PAM_IGNORE as usize] = PAM_ACTION_IGNORE;
                            utpam_set_default_control(&mut actions, PAM_ACTION_IGNORE);
                        }
                        "include" => {
                            D!("*PAM_F_INCLUDE*");
                            pam_include = 1;
                            substack = 0;
                        }
                        "substack" => {
                            D!("*PAM_F_SUBSTACK*");
                            pam_include = 1;
                            substack = 1;
                        }
                        _ => {
                            D!("will need to parse {}", tok);
                            utpam_parse_control(&mut actions, &tok);
                            utpam_set_default_control(&mut actions, PAM_ACTION_BAD);
                        }
                    }
                }
                None => {
                    /* no module name given */
                    D!("no control flag supplied");
                    pam_syslog!(
                        &utpamh,
                        LOG_ERR,
                        "({}) no control flag supplied",
                        this_service
                    );
                    utpam_set_default_control(&mut actions, PAM_ACTION_BAD);
                    handler_type = PAM_HT_MUST_FAIL;
                }
            }

            //读取调用路径或者认证模块
            match utpam_tokenize(None, &mut buf) {
                Some(tok) => {
                    if pam_include == 1 {
                        if substack == 1 {
                            res = utpam_add_handler(
                                utpamh,
                                PAM_HT_SUBSTACK,
                                other,
                                stack_level,
                                module_type,
                                &mut actions,
                                &Some(tok.clone()),
                                argc,
                                &argv,
                            );
                            if res != PAM_SUCCESS {
                                pam_syslog!(&utpamh, LOG_ERR, "error adding substack {}", tok);
                                D!("failed to load module - aborting");
                                return PAM_ABORT;
                            }
                        }
                        if utpam_load_conf_file(
                            utpamh,
                            Some(tok.clone()),
                            Some(this_service.clone()),
                            module_type,
                            include_level + 1,
                            stack_level + substack,
                            #[cfg(feature = "PAM_READ_BOTH_CONFS")]
                            !other,
                        ) == PAM_SUCCESS
                        {
                            //更新循环
                            x = utpam_line_assemble(&mut f, &mut buffer, repl.clone());
                            continue;
                        }

                        utpam_set_default_control(&mut actions, PAM_ACTION_BAD);
                        mod_path = None;
                        handler_type = PAM_HT_MUST_FAIL;
                        //nexttok = None;
                    } else {
                        mod_path = Some(tok);
                        D!("mod_path = {:?}", mod_path);
                    }
                }
                None => {
                    /* no module name given */
                    D!("no module name supplied");
                    pam_syslog!(
                        &utpamh,
                        LOG_ERR,
                        "({}) no module name supplied",
                        this_service
                    );
                    mod_path = None;
                    handler_type = PAM_HT_MUST_FAIL;
                }
            }

            if let Some(buf) = buf {
                if utpam_mkargv(buf, &mut argv, &mut argc) == 0 {
                    D!("failed to allocate argument vector");
                    pam_syslog!(
                        &utpamh,
                        LOG_ERR,
                        "({}) argument vector allocation failed",
                        this_service
                    );
                    mod_path = None;
                    handler_type = PAM_HT_MUST_FAIL;
                }
            }

            res = utpam_add_handler(
                utpamh,
                handler_type,
                other,
                stack_level,
                module_type,
                &mut actions,
                &mod_path,
                argc,
                &argv,
            );
            if res != PAM_SUCCESS {
                let mod_path = match mod_path {
                    Some(path) => path,
                    None => "unknown file".to_string(),
                };
                pam_syslog!(&utpamh, LOG_ERR, "error loading {}", mod_path);
                D!("failed to load module - aborting");
                return PAM_ABORT;
            }
        }
        //更新循环
        x = utpam_line_assemble(&mut f, &mut buffer, repl.clone());
    }

    if x < 0 {
        PAM_ABORT
    } else {
        PAM_SUCCESS
    }
}

///从模块路径中提取模块名称，如果路径无效则返回 None
fn extract_modulename(mod_path: &str) -> Option<String> {
    //如果路径为空
    if mod_path.trim().is_empty() {
        return None;
    }
    let path = PathBuf::from(mod_path);
    let file_stem = path.file_stem(); // 获取文件名（不包括扩展名）

    let file_stem_str = match file_stem {
        Some(stem) => stem.to_str()?,
        None => return None,
    };

    //检查路径是否有效
    if file_stem_str.is_empty() || file_stem_str == "?" {
        return None;
    }

    Some(file_stem_str.into())
}

//加载模块
fn utpam_load_module(
    utpamh: &mut Vec<LoadedModule>,
    mod_path: String,
    handler_type: u8,
) -> Option<&LoadedModule> {
    let mods = utpamh;

    D!("loading module {}", mod_path);

    //遍历模块列表，检查是否存在mod_path模块。
    let x = mods.iter().position(|m| m.name == mod_path);

    match x {
        Some(index) => {
            //直接返回匹配到的模块
            Some(&mods[index])
        }
        None => {
            /*处理没有匹配到模块的情况*/

            //创建一个新的模块
            let mut newmod = LoadedModule {
                name: mod_path.clone(),
                moule_type: 0,
                dl_handle: None,
            };

            D!("utpam_dlopen({})", mod_path);
            //加载模块
            match utpam_dlopen(mod_path.clone().to_string()) {
                Ok(handle) => newmod.dl_handle = Some(handle),
                Err(_) => {
                    //处理带有占位符的路径字符串，并根据具体的架构替换占位符以加载正确的动态库
                    let isa_pos = mod_path.find("$ISA");
                    if isa_pos.is_some() {
                        let target_arch = match ARCH {
                            "x86_64" => "x86_64",
                            "aarch64" => "aarch64",
                            _ => panic!("Unsupported architecture"),
                        };
                        let real_mod_path = mod_path.replace("$ISA", target_arch);

                        //重新加载模块
                        match utpam_dlopen(real_mod_path) {
                            Ok(handle) => {
                                D!("module added successfully");
                                newmod.moule_type = PAM_MT_DYNAMIC_MOD;
                                newmod.dl_handle = Some(handle);
                            }
                            Err(e) => {
                                newmod.dl_handle = None;
                                newmod.moule_type = PAM_MT_FAULTY_MOD;

                                if handler_type != PAM_HT_SILENT_MODULE {
                                    D!("utpam_dlopen({}) failed", mod_path);
                                    log::debug!(
                                        "{} {} {} {}",
                                        LOG_ERR,
                                        "error loading: ",
                                        mod_path,
                                        e
                                    );
                                }
                            }
                        };
                    }
                    D!("Error loading module");
                }
            };

            //添加到模块列表
            let index = mods.len();
            mods.push(newmod);

            //返回新模块
            Some(&mods[index])
        }
    }
}

//添加处理程序
fn utpam_add_handler(
    utpamh: &mut Box<UtpamHandle>,
    handler_type: u8,
    other: bool,
    stack_level: i32,
    module_type: i32,
    actions: &mut [i32],
    mod_paths: &Option<String>,
    argc: i32,
    argv: &[String],
) -> u8 {
    D!("called.");
    D!(
        "adding module_type {}, handler_type {}, module {:?}",
        module_type,
        handler_type,
        mod_paths
    );

    let mut load_module = None;

    let mut mod_type: u8 = PAM_MT_FAULTY_MOD;
    let unknown_module = UNKNOWN_MODULE.to_string();

    //处理模块路径
    let mod_path = match mod_paths {
        Some(s) => s,
        None => &unknown_module,
    };

    //根据模块路径获取模块类型
    if (handler_type == PAM_HT_MODULE || handler_type == PAM_HT_SILENT_MODULE)
        && mod_paths.is_some()
    {
        let new_path = PathBuf::from(DEFAULT_MODULE_PATH).join(mod_path);
        if mod_path.starts_with('/') {
            load_module = utpam_load_module(
                &mut utpamh.handlers.module,
                mod_path.to_string(),
                handler_type,
            );
        } else if new_path.exists() {
            load_module = utpam_load_module(
                &mut utpamh.handlers.module,
                new_path.to_string_lossy().to_string(),
                handler_type,
            );
        } else {
            pam_syslog!(&utpamh, LOG_ERR, "cannot malloc full mod path",);
            return PAM_ABORT;
        }

        match load_module {
            Some(m) => {
                mod_type = m.moule_type;
            }
            None => return PAM_ABORT,
        };
    }

    //决定使用哪个处理程序列表
    let the_handlers = if other {
        &mut utpamh.handlers.other
    } else {
        &mut utpamh.handlers.conf
    };

    //匹配处理程序类型
    let (handler_p, sym, handler_p2, sym2) = match module_type {
        PAM_T_AUTH => (
            &mut the_handlers.authenticate,
            "utpam_sm_authenticate",
            Some(&mut the_handlers.setcred),
            "utpam_sm_setcred",
        ),
        PAM_T_SESS => (
            &mut the_handlers.open_session,
            "utpam_sm_open_session",
            Some(&mut the_handlers.close_session),
            "utpam_sm_close_session",
        ),
        PAM_T_ACCT => (&mut the_handlers.acct_mgmt, "utpam_sm_acct_mgmt", None, ""),
        PAM_T_PASS => (&mut the_handlers.chauthtok, "utpam_sm_chauthtok", None, ""),
        _ => {
            /* Illegal module type */
            D!("illegal module type {}", module_type);
            return PAM_ABORT;
        }
    };

    if mod_type != PAM_MT_DYNAMIC_MOD && mod_type != PAM_MT_FAULTY_MOD {
        D!("illegal module library type; {}", mod_type);
        pam_syslog!(
            &utpamh,
            LOG_ERR,
            "internal error: module library type not known: {};{}",
            sym,
            mod_type
        );
        return PAM_ABORT;
    }

    let mut handle = None;
    if let Some(s) = load_module {
        handle = s.dl_handle.as_ref();
    };
    let mut func = None;
    if mod_type == PAM_MT_DYNAMIC_MOD {
        // 获取函数指针
        match utpam_dlsym(&handle, sym.as_bytes()) {
            Ok(fun) => {
                func = Some(*fun);
            }
            Err(_) => {
                log::debug!(
                    "{}, {:?} unable to resolve symbol: {}",
                    LOG_ERR,
                    mod_path,
                    sym
                );
            }
        }
    }
    let mut func2 = None;
    if mod_type == PAM_MT_DYNAMIC_MOD && !sym2.is_empty() {
        match utpam_dlsym(&handle, sym2.as_bytes()) {
            Ok(fun) => {
                func2 = Some(*fun);
            }
            Err(_) => {
                log::debug!(
                    "{}, {:?} unable to resolve symbol: {}",
                    LOG_ERR,
                    mod_path,
                    sym2
                );
            }
        }
    }

    let path = match extract_modulename(mod_path) {
        Some(mod_name) => mod_name,
        None => return PAM_ABORT,
    };
    utpamh.cached_retval = Rc::new(RefCell::new(_PAM_INVALID_RETVAL));
    let handler = Handler {
        handler_type,
        func,
        actions: actions.to_owned(),
        argc,
        argv: argv.to_owned(),
        next: None,
        mod_name: path,
        stack_level,
        grantor: 0,
    };
    // 将新 Handler 插入链表末尾
    append_handler(handler_p, handler);

    if let Some(handler_p2) = handler_p2 {
        let path = match extract_modulename(mod_path) {
            Some(mod_name) => mod_name,
            None => return PAM_ABORT,
        };
        utpamh.cached_retval = Rc::new(RefCell::new(_PAM_INVALID_RETVAL));
        let handler = Handler {
            handler_type,
            func: func2,
            actions: actions.to_owned(),
            argc,
            argv: argv.to_owned(),
            next: None,
            mod_name: path,
            stack_level,
            grantor: 0,
        };
        append_handler(handler_p2, handler);
    }

    D!("returning successfully");

    PAM_SUCCESS
}

//在链表的末尾插入一个新的 Handler 节点
fn append_handler(handlers: &mut Option<Box<Handler>>, new_handler: Handler) {
    let mut current = handlers;

    //循环遍历链表，直到找到最后一个节点。如果当前节点的 next 是 None，则插入新的 Handler
    while let Some(ref mut node) = current {
        if node.next.is_none() {
            node.next = Some(Box::new(new_handler));
            return;
        }
        current = &mut node.next;
    }

    // 如果链表为空，直接插入新的 Handler
    if current.is_none() {
        *current = Some(Box::new(new_handler));
    }
}
